<?php defined('SYSPATH') OR die('No direct access allowed.');
/**
 * The Micro Framework Heart
 * 
 * @package    Core
 * @author     Andres Vidal
 * @copyright  (c) 2009 Andres Vidal
 * @license    http://www.andresvidal.com/license/micro
 */

final class Micro {
	
	// The final output that will displayed by Micro
	public static $output = '';

	// The current user agent
	public static $user_agent;
	
	// The included paths
	public static $include_paths;

	// Configuration
	private static $configuration;	
	
	
	/**
	 * Sets up the PHP environment.
	 *
	 * @return  void
	 */
	public static function setup()
	{
		static $run;
		
		// This function can only be run once
		if ($run === TRUE)
			return;
			
		// Set the user agent
		self::$user_agent = ( ! empty($_SERVER['HTTP_USER_AGENT']) ? trim($_SERVER['HTTP_USER_AGENT']) : '');
		
		// Set autoloader
		spl_autoload_register( array('Micro', 'auto_load') );
		
		// Send default text/html UTF-8 header
		header('Content-Type: text/html; charset=UTF-8');
		
		// Setup is complete, prevent it from being run again
		$run = TRUE;
	}
	
	/**
	 * Get a config item.
	 *
	 * @param   string   item name
	 * @return  mixed    returns FALSE if key not found
	 */
	public static function config($key)
	{
		if (self::$configuration === NULL)
		{
			// Load the configuration file
			require SYSPATH.'config'.EXT;
		}
		
		if ( isset($config[$key]) )
			return $config[$key];
			
		return FALSE;
	}
	
	/**
	 * Provides class auto-loading.
	 *
	 * @param   string  name of class
	 */
	public static function auto_load($class)
	{
		if (class_exists($class, FALSE))
			return TRUE;

		// Find the file and Load the class
		if ( $file = self::find_file($class) )
		{
			require $file;	
		}
		else
		{
			// throw exception
		}
	}
	
	/**
	 * Find a resource file in a given directory. 
	 *
	 * @todo             There might be conflicts when naming class files the same in PAGES. Needs a check of whether or not to include PAGES  
	 * @todo             The $search terms need work
	 * @param   string   name of file name
	 * @return  string   if the file is found
	 * @return  FALSE    if the file is not found
	 */
	public static function find_file( $filename )
	{	
		
		// Add system paths
		self::$include_paths = array(SYSPATH, CLASSES);
		
		// Load, Parse and Merge Config include_paths
		if ( self::config('include_paths') ){
			foreach (self::config('include_paths') as $path)
				{
					if ($path = str_replace('\\', '/', realpath($path)))
					{
						// Add a valid path
						self::$include_paths[] = $path.'/';
					}
				}
		}
		
		// Search file with added EXT
		$search = $filename . EXT;

		// Load include paths
		$paths = self::$include_paths;
		
		foreach ($paths as $path)
			{
				if (is_file($path.$search ))
				{
					// A matching file has been found
					$found = $path.$search;

					// Stop searching
					break;
				}
				else
				{
					// Nothing was found, return FALSE
					$found = FALSE;
				}
			}

		return $found;
	}
	
	/**
	 * Loads the requested PHP/HTML file into a string. Inserts global Micro variables. Processes the string w/PHP inside and prints it.
	 *
	 * @param   string  final output that will displayed
	 * @return  void
	 */
	public static function render($output)
	{
		$output = file_get_contents( self::$output );
		
		Benchmark::stop(SYSTEM_BENCHMARK.'_total_execution');
		
		if (self::config('render_stats') === TRUE)
		{
			// Fetch memory usage in MB
			$memory = function_exists('memory_get_usage') ? (memory_get_usage() / 1024 / 1024) : 0;

			// Fetch benchmark for page execution time
			$benchmark = Benchmark::get(SYSTEM_BENCHMARK.'_total_execution');

			// Replace the global template variables
			$output = str_replace(
				array
				(
					'{micro_version}',
					'{execution_time}',
					'{memory_usage}',
				),
				array
				(
					MICRO_VERSION,
					$benchmark['time'],
					number_format($memory, 2).'MB',
				),
				$output
			);
		}
		
		// Final Output. Evaluates the loaded string (PHP or HTML) for PHP and executes as normal.
		eval("?>" . $output . "<?"); //Thanks http://us3.php.net/manual/en/function.eval.php#88820
	}
}